﻿#ifndef LOOPBUFFER_H
#define LOOPBUFFER_H

#include <QIODevice>

class QMutex;
class QSemaphore;

class LoopBuffer : public QIODevice
{
    Q_OBJECT
public:

    /**
     * @brief The WriteMode enum
     * 写入支持三种模式：
     * 写入限制：空间总大小小于一次写入量，写入为0，用户层需要判断写入是否成功（这里并不支持增量写入，因为很多时候上层数据不支持）
     * 写入无限：待写入值大于预设大小，则会按照“循环覆盖”写入
     * 写入余量限制：当余量小于待写入大小，返回0。注意：当可用空间不足，而读取又超过的话，会造成读写均不可用！
     */
    enum WriteMode{
        WriteTotalLimited,  // default
        WriteTotalUnlimited,
        WriteRemainLimited
    };
public:
    static int getAudioSuggestSize(int sample,int channel,int sampleBits);
    LoopBuffer(qint64 size,bool multiThread = false);
    ~LoopBuffer();
public:
    void setWriteMode(WriteMode mode);
    void clear();
    virtual bool open(OpenMode mode) override;

    /**
     * @brief readData
     * @param data
     * @param maxlen
     * @return
     */
    virtual qint64 readData(char *data, qint64 maxlen) override;

    /**
     * @brief writeData,两种方式，一次写入总值在一个范围内，一次写入的总值直接覆盖（大于1倍的数据量）
     * @param data
     * @param len greater than 0
     * @return
     */
    virtual qint64 writeData(const char *data, qint64 len) override;

protected:

private:
    bool m_multiThread = false; /* 支持多线程信号量读取 */

    QMutex * m_mutex = nullptr;
    QSemaphore *m_sem = nullptr;

    QByteArray * m_buffer = nullptr;
    const int m_sizeMax;
    int m_wpos;
    int m_rpos;
    int m_remain;

    int m_readNullSize = 0;

    WriteMode m_mode = WriteTotalLimited;

    void dumpInfo(const QString &info,QVariant value);
    void boundaryTest();
};

#endif // LOOPBUFFER_H
